---------------Farmfiler---------------
A 4am crack                  2022-12-26
---------------------------------------

Name: Farmfiler
Version: 03.11.83
Genre: productivity
Year: 1983
Publisher: Farmplan Computer Systems
Platform: Apple ][+ or later
Media: 5.25-inch disk
Sides: 4
OS: DOS 3.3
Previous cracks: none

     _____________________________
    {                             }
    { "There are more things in   }
    {  Heaven and Earth, Horatio, }
    {  than are dreamt of in your }
    {  philosophy.                }
    {                             }
    {                 Hamlet, I.5 }
    {_____________________________}


                   ~

               Chapter 0
 In Which Various Automated Tools Fail
          In Interesting Ways


COPYA
  immediate read error

Locksmith Fast Disk Backup
  able to copy tracks 0-2 only

EDD 4 bit copy (no sync, no count)
  no errors, copy works

Copy ][+ nibble editor
  no obvious shenanigans (standard
  address and data prologues and
  epilogues, standard address field
  structure)

                 --v--

TRACK: 03  START: 2965  LENGTH: 183F

2940: FF FF FF FF FF FF FF FF   VIEW
2948: FF FF FF FF FF FF FF FF
2950: FF FF FF FF FF FF FF FF
2958: FF FF FF FF FF FF FF FF
2960: FF FF FF FF FF D5 AA 96  <-2965
2968: FF FE AB AE AA AA FE FA
2970: DE AA E9 99 FF FF FF FF
2978: FF FF FF FF D5 AA AD AE
2980: FE DA FF EC A6 AE E6 A7

                 --^--

Disk Fixer
  Given that DOS tracks (0-2) appear
  unprotected and the rest of the disk
  appears protected, I would expect the
  bootloader to jump to some custom
  routine after loading DOS, but it
  only seems to set the Applesoft RUN
  flag (makes all interactive commands
  re-RUN the current program, a weird
  little trick that nonetheless has
  nothing to do with on-disk structural
  protection)

                 --v--

T00,S01
----------- DISASSEMBLY MODE ----------
003A:20 93 B7       JSR   $B793
003D:A2 FF          LDX   #$FF
003F:9A             TXS
0040:8E EB B7       STX   $B7EB
0043:4C C8 BF       JMP   $BFC8
0046:20 89 FE       JSR   $FE89
0049:A9 80          LDA   #$80      <--
004B:65 D6          ADC   $D6
004D:85 D6          STA   $D6
004F:4C 84 9D       JMP   $9D84

                 --^--

Furthermore, there is nothing special
at $B793, which just calls $B7B5 in a
loop as usual. There is nothing special
at $B7B5, which just calls $BD00 as
usual. There are no unusual JMPs or
JSRs at $BD00 either. The patch at
$BFC8 just does the usual thing and
returns to $B746. Nor are there any
unusual callouts at $9D84, which exits
via $A180 as usual. And there is
nothing suspicious at $A180.

That's a whole lot of normality for a
disk that is definitely not normal.

Passport
  Initial success in capturing the RWTS
  and tracing the bootloader, followed
  by immediate failure.

                 --v--

Reading from S6,D1
T00,S00 Found DOS 3.3 bootloader
Using disk's own RWTS
T22,S0F Switching to built-in RWTS

T22,S0F Fatal read error

Passport does not work on this disk.

                 --^--

I have to admit, it is surprising to
see Passport fail so quickly on a disk
that is, by all indications, almost
entirely normal -- especially after 6+
years of development and 2999 cracks.
But there are more edge cases in Heaven
and Earth, &c.

Why didn't COPYA work?
  something funky going on with
  tracks 3+

Why didn't Locksmith FDB work?
  ditto

EDD worked. What does that tell us?
  no half or quarter tracks
  almost certainly no nibble check
  (just as-yet-unexplained structural
  changes)

Next steps:

  1. capture RWTS with AUTOTRACE
  2. convert disk to standard format
     with Advanced Demuffin
  3. patch RWTS to read standard format

                   ~

               Chapter 1
In Which We Attempt To Use The Original
    Disk As A Weapon Against Itself
        And It Does Not Go Well


[S6,D1=original disk]
[S6,D2=blank disk]
[S5,D1=my work disk]

]PR#5
CAPTURING BOOT0
...reboots slot 6...
...reboots slot 5...
SAVING BOOT0
CAPTURING BOOT1
...reboots slot 6...
...reboots slot 5...
SAVING BOOT1
SAVING RWTS

]BRUN ADVANCED DEMUFFIN 1.5

["5" to switch to slot 5]

["R" to load a new RWTS module]
  --> At $B8, load "RWTS" from drive 1

["6" to switch to slot 6]

["C" to convert disk]

                 --v--

ADVANCED DEMUFFIN 1.5    (C) 1983, 2014
ORIGINAL BY THE STACK    UPDATES BY 4AM
=======PRESS ANY KEY TO CONTINUE=======
TRK:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
+.5:
    0123456789ABCDEF0123456789ABCDEF012
SC0:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC1:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC2:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC3:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC4:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC5:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC6:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC7:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC8:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC9:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SCA:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SCB:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SCC:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SCD:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SCE:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SCF:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
=======================================
16SC $00,$00-$22,$0F BY1.0 S6,D1->S6,D2

                 --^--

This was not the rousing success I was
hoping for.

Somewhat stuck, I decided to compare
tracks 0-2 to a standard DOS 3.3 disk,
to see what I had missed. This is made
only slightly more difficult by the
fact that DOS 3.3 went through several
minor revisions, each of which added
more and more patch code to previously
unused regions of track 0. But I did,
at last, find this difference:

                 --v--

BDB9-   20 00 B8    JSR   $B800
BDBC-   A0 30       LDY   #$30
BDBE-   8C 78 05    STY   $0578
BDC1-   AE F8 05    LDX   $05F8
BDC4-   20 00 BF    JSR   $BF00   <-- !
BDC7-   90 24       BCC   $BDED
BDC9-   CE 78 05    DEC   $0578
BDCC-   10 F3       BPL   $BDC1

                 --^--

On a standard DOS 3.3 disk, the call at
$BDC4 is to $B944, which finds and
parses the next available address field
and sets some values in zero page with
the results. $BF00 isn't an entry point
for anything.

But on this disk, it is.

                 --v--

; call the usual routine to parse the
; next address field
BF00-   20 44 B9    JSR   $B944

; save the result
BF03-   08          PHP

; get the slot number (x16) from the
; RWTS parameter table
BF04-   A0 01       LDY   #$01
BF06-   B1 48       LDA   ($48),Y

; compare to ... somewhere in zero page
BF08-   C5 18       CMP   $18

; if not equal (to what?) then skip
; ahead
BF0A-   D0 11       BNE   $BF1D

; now get the drive number from the
; RWTS parameter table
BF0C-   C8          INY
BF0D-   B1 48       LDA   ($48),Y

; if it's not drive 1, then skip ahead
BF0F-   C9 01       CMP   #$01
BF11-   D0 0A       BNE   $BF1D

; now get the track number from the
; RWTS parameter table
BF13-   C8          INY
BF14-   C8          INY
BF15-   B1 48       LDA   ($48),Y

; if it's less than 3 then skip ahead
BF17-   C9 03       CMP   #$03
BF19-   30 02       BMI   $BF1D

; oh my God, I just figured it out
BF1B-   46 2E       LSR   $2E
BF1D-   A9 80       LDA   #$80
BF1F-   85 D6       STA   $D6
BF21-   28          PLP
BF22-   60          RTS

                 --^--

This is actually brilliant, and it's
something I've never seen before. As I
mentioned, the routine at $B944 finds
and parses the next available address
field, and stores results in zero page.
Specifically, it stores the decoded
disk volume number in $2F, the track
number in $2E, and the sector number in
$2D. Notably, it does not do anything
with those values beyond store them.
(There is a checksum embedded in the
address field, which it does validate.)
But the rest of the RWTS logic, like
"is this a sector we care about?" or
"is the drive head on the right track?"
resides the caller.

This routine at $BF00 inserts itself
between the parser at $B944 and the
caller at $BDxx, and does exactly one
thing: if we're reading or writing to
track 3+ in a specific slot and drive,
it takes the track number stored in the
address field and divides it by 2.

                   ~

               Chapter 2
     In Which We Retrace Our Steps


This still leaves one unanswered
question: what is in zero page $18, and
where is it initialized? I guess that's
two questions.

The answer to both questions lies in
the early bootloader, which I had
passed over with a minimum of concern,
only to find the next steps would not
work.

Here is track 0, sector 1, loaded into
memory at $B700:

                 --v--

T00,S01
----------- DISASSEMBLY MODE ----------
; blah blah blah
0000:8E E9 B7       STX   $B7E9
0003:8E F7 B7       STX   $B7F7
0006:A9 01          LDA   #$01
0008:8D F8 B7       STA   $B7F8
000B:8D EA B7       STA   $B7EA
000E:AD E0 B7       LDA   $B7E0
0011:8D E1 B7       STA   $B7E1
0014:A9 02          LDA   #$02
0016:8D EC B7       STA   $B7EC
0019:A9 04          LDA   #$04
001B:8D ED B7       STA   $B7ED
001E:AC E7 B7       LDY   $B7E7
0021:88             DEY
0022:8C F1 B7       STY   $B7F1
0025:A9 01          LDA   #$01
0027:8D F4 B7       STA   $B7F4

; wait a minute, what's all this then
002A:86 18          STX   $18

                 --^--

And there it is: zero page $18 holds
the boot slot (x16). When we're reading
from that slot, and drive 1, track
numbers in address fields are cut in
half before being interpreted.

That also explains why Advanced
Demuffin couldn't read the disk, even
with the disk's own RWTS: we were
missing a crucial initialization in
zero page $18. Let's correct that.

                   ~

               Chapter 3
In Which We Attempt To Use The Original
    Disk As A Weapon Against Itself
                 Again
      But This Time With Feeling


[S6,D1=original disk]
[S6,D2=blank disk]
[S5,D1=my work disk]

]PR#5
...
]BLOAD ADVANCED DEMUFFIN 1.5
]CALL -151

; standard IOB
1400-   4A          LSR
1401-   8D 22 0F    STA   $0F22
1404-   8C 23 0F    STY   $0F23
1407-   8E 27 0F    STX   $0F27
140A-   A9 01       LDA   #$01
140C-   8D 20 0F    STA   $0F20
140F-   8D 2A 0F    STA   $0F2A

; custom for this disk: take the source
; slot and copy it into zero page $18
; before each read
1412-   AD 1F 0F    LDA   $0F1F
1415-   85 18       STA   $18

; now call the disk's original RWTS
1417-   A9 0F       LDA   #$0F
1419-   A0 1E       LDY   #$1E
141B-   4C 00 BD    JMP   $BD00

With this change, we should be able to
read the entire disk.

; launch Advanced Demuffin
*800G

["5" to switch to slot 5]

["R" to load a new RWTS module]
  --> At $B8, load "RWTS" from drive 1

["6" to switch to slot 6]

["C" to convert disk]

                 --v--

ADVANCED DEMUFFIN 1.5    (C) 1983, 2014
ORIGINAL BY THE STACK    UPDATES BY 4AM
=======PRESS ANY KEY TO CONTINUE=======
TRK:...................................
+.5:
    0123456789ABCDEF0123456789ABCDEF012
SC0:...................................
SC1:...................................
SC2:...................................
SC3:...................................
SC4:...................................
SC5:...................................
SC6:...................................
SC7:...................................
SC8:...................................
SC9:...................................
SCA:...................................
SCB:...................................
SCC:...................................
SCD:...................................
SCE:...................................
SCF:...................................
=======================================
16SC $00,$00-$22,$0F BY1.0 S6,D1->S6,D2

                 --^--

Glorious. We still have a disk that
treats the disk in drive 1 of the boot
slot as protected, but we can fix that
with a one-byte patch by neutering the
LSR on the track number.

T00,S09,$1B: 46 -> 24

Now the custom routine at $BF00 looks
like this:

                 --v--

T00,S09
----------- DISASSEMBLY MODE ----------
0015:B1 48          LDA   ($48),Y
0017:C9 03          CMP   #$03
0019:30 02          BMI   $001D
001B:24 2E          BIT   $2E       <--
001D:A9 80          LDA   #$80
001F:85 D6          STA   $D6
0021:28             PLP
0022:60             RTS

                 --^--

BIT functions here as a no-op (well
technically it will set some status
flags, but we're restoring the original
flags a few instructions later). We'll
let it go through the motions to decide
whether to treat this disk specially,
then at the crucial moment, we'll do
nothing special.

Disks 2-4 are unprotected.

Quod erat liberandum.

---------------------------------------
A 4am crack                    No. 3000
------------------EOF------------------
